package com.vhall.component.plugin.core.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import com.vhall.component.entity.paas.AddKeyFrameDescReqVO;
import com.vhall.component.entity.paas.PaasMessageListRspDTO;
import com.vhall.component.entity.record.vo.CutRecordReqVO;
import com.vhall.component.entity.record.vo.RecordDownQualityReqVO;
import com.vhall.component.entity.record.vo.RecordDownReqVO;
import com.vhall.component.entity.room.dto.RoomsEntityDTO;
import com.vhall.component.entity.room.vo.FirstFrameFromVideoVO;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.plugin.common.constant.HttpConstant;
import com.vhall.component.plugin.common.constant.PaasCommonConstant;
import com.vhall.component.plugin.common.constant.RoomConstant;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.utils.HttpClientResult;
import com.vhall.component.plugin.common.utils.HttpPoolClientUtil;
import com.vhall.component.plugin.common.utils.JsonUtil;
import com.vhall.component.plugin.core.enums.SendMessageTypeEnum;
import com.vhall.component.plugin.core.service.dto.BigDataBroadcastRecordReportDTO;
import com.vhall.component.plugin.core.service.event.PaasMessageReqDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.text.MessageFormat;
import java.util.*;

/**
 * @author yongzheng.xu
 * @date 2021/4/25 13:50
 */
@Slf4j
@Service
public class PaasService extends BaseHttpService {
    @Value("${paas.host}")
    private String api;

    @Value("${paas.apps.lite.appId}")
    private String appId;

    @Value("${paas.apps.lite.appSecret}")
    private String appSecret;

    @Value("${paas.bu}")
    private String bu;

    @Value("${paas.stream-domain}")
    private String pullStreamUrl;

    @Value("${vhall.big-data.report-prefix-url:http://10.110.110.101:8001}")
    private String prefixUrl;


    public String getAppId() {
        return appId;
    }

    public String getAppSecret() {
        return appSecret;
    }


    public JSONObject documentCreate(File file) {
        Long time = DateUtil.currentSeconds();
        Map<String, Object> map = new HashMap<>(8);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, time);
        map.put("bu", bu);
        //创建文档添加静态类型
        map.put("conversion_type", "only_static");
        String url = api + "/api/v2/document/create";
        long start = System.currentTimeMillis();
        HttpResponse rsp = HttpUtil.createPost(url).timeout(1000 * 60 * 2).contentType("multipart/form-data").form("document", file).form("bu", bu)
                .form(PaasCommonConstant.APP_ID_KEY, appId).form(PaasCommonConstant.SIGNED_AT, time).form("conversion_type", "only_static").form(PaasCommonConstant.SIGN, sign(map)).execute();
        JSONObject result = JSON.parseObject(rsp.body());
        String msg = result.getString(HttpConstant.MSG);
        Integer code = result.getInteger(HttpConstant.CODE);
        if (code != HttpConstant.SUCCESS_CODE) {
            log.warn("三方接口,失败,path={}, rsp={}", url, rsp.body());
            throw new BusinessException(code, msg, "error.paas.doc");
        }
        long end = System.currentTimeMillis();
        log.info(MessageFormat.format("文档上传耗时：【{0}】",end-start));
        return result.getJSONObject(HttpConstant.DATA);
    }

    public JSONObject documentInfo(String id) {
        Map<String, Object> map = new HashMap<>(8);
        map.put("document_id", id);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));

        String url = api + "/api/v2/document/get-info";
        String rsp = httpPostAndPrintLog(url, map);

        JSONObject result = JSON.parseObject(rsp);
        String msg = result.getString(HttpConstant.MSG);
        Integer code = result.getInteger(HttpConstant.CODE);
        if (code != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,失败,path={}, rsp={}", url, rsp);
            throw new BusinessException(code, msg, "error.paas");
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    public void documentDel(String id) {
        Map<String, Object> map = new HashMap<>(8);
        map.put("document_id", id);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));

        String url = api + "/api/v2/document/delete";
        String rsp = httpPostAndPrintLog(url, map);

        JSONObject result = JSON.parseObject(rsp);
        String msg = result.getString(HttpConstant.MSG);
        Integer code = result.getInteger(HttpConstant.CODE);
        if (code != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,失败,path={}, rsp={}", url, rsp);
            throw new BusinessException(code, msg, "error.paas");
        }
    }

    public String sign(Map<String, Object> param) {
        param.remove(PaasCommonConstant.SIGN);
        StringBuilder str = new StringBuilder();
        Object[] keyArr = param.keySet().toArray();
        Arrays.sort(keyArr);
        for (Object key : keyArr) {
            String keyStr = (String) key;
            if (param.get(keyStr) != null && !"null".equals(param.get(keyStr))) {
                str.append(key).append(param.get(keyStr));
            }
        }
        str = new StringBuilder(appSecret + str + appSecret);
        return MD5.create().digestHex(str.toString());
    }

    public JSONObject sendMessage(String channel, String body) {
        return sendMessage(channel, body, null, "service_room", "pc_browser", 1);
    }

    /**
     * 根据消息实体处理
     *
     * @param paasMessageReq 消息实体
     * @return 发送结果
     */
    public JSONObject sendMessage(PaasMessageReqDTO paasMessageReq) {
        return sendMessage(paasMessageReq.getChannelId(), paasMessageReq.getBody(),paasMessageReq.getContext(), paasMessageReq.getThirdUserId(),
                paasMessageReq.getType(), paasMessageReq.getClient(), paasMessageReq.getIsCache());
    }

    public JSONObject sendMessage(String channel, String body, String thirdUserId, String type, String client, Integer isCache) {
        String url = api + "/api/v2/message/send";
        thirdUserId = StringUtils.isNotBlank(thirdUserId) ? thirdUserId : null;
        type = StringUtils.isBlank(type) ? "service_room" : type;
        client = StringUtils.isBlank(client) ? "pc_browser" : client;
        isCache = isCache == null ? 1 : isCache;
        HashMap<String, Object> param = Maps.newHashMap();
        param.put(PaasCommonConstant.CHANNEL_ID_KEY, channel);
        param.put("type", type);
        param.put("client", client);
        param.put("body", body);
        param.put("is_cache", isCache);
        if (thirdUserId != null) {
            param.put("third_party_user_id", thirdUserId);
        }
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));

        String rspStr = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rspStr);
        if (isJsonArray(result.get(HttpConstant.DATA))) {
            return new JSONObject();
        } else {
            return result.getJSONObject(HttpConstant.DATA);
        }
    }
    public JSONObject sendMessage(String channel, String body,String context, String thirdUserId, String type, String client, Integer isCache) {
        String url = api + "/api/v2/message/send";
        thirdUserId = StringUtils.isNotBlank(thirdUserId) ? thirdUserId : null;
        type = StringUtils.isBlank(type) ? "service_room" : type;
        client = StringUtils.isBlank(client) ? "pc_browser" : client;
        isCache = isCache == null ? 1 : isCache;
        HashMap<String, Object> param = Maps.newHashMap();
        param.put(PaasCommonConstant.CHANNEL_ID_KEY, channel);
        param.put("type", type);
        param.put("client", client);
        param.put("body", body);
        param.put("is_cache", isCache);
        if (thirdUserId != null) {
            param.put("third_party_user_id", thirdUserId);
        }
        if (StrUtil.isNotBlank(context)) {
            param.put("context", context);
        }
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));

        String rspStr = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rspStr);
        if (isJsonArray(result.get(HttpConstant.DATA))) {
            return new JSONObject();
        } else {
            return result.getJSONObject(HttpConstant.DATA);
        }
    }

    public void sendCustomMessage(String channelId, Integer accountId, String body, String type) {
        String url = api + "/api/v2/message/send";
        Map<String, Object> params = new HashMap<>(16);
        params.put(PaasCommonConstant.CHANNEL_ID_KEY, channelId);
        params.put("type", type);
        params.put("third_party_user_id", accountId);
        params.put("client", "pc_browser");
        params.put("body", body);
        params.put(PaasCommonConstant.APP_ID_KEY, appId);
        params.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        // 构建sign
        params.put(PaasCommonConstant.SIGN, sign(params));
        String rspStr = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rspStr);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(params), rspStr);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
    }

    private boolean isJsonArray(Object data) {
        String obj = data.toString();
        try {
            JSON.parseArray(obj);
            if (obj.startsWith("[")) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            log.error("解析失败,原因:{}", e.getMessage());
            return false;
        }
    }

    /**
     * 请求paas（连接池模式）
     *
     * @param url    请求地址
     * @param params 请求参数
     * @return 响应内容
     * @author yuanzh
     */
    private JSONObject post2Paas(String url, Map<String, Object> params) {
        try {
            HttpClientResult httpClientResult = HttpPoolClientUtil.doPost(url, params, 10 * 1000, 10 * 1000, "PAAS服务");
            return JSON.parseObject(httpClientResult.getContent());
        } catch (Exception e) {
            log.warn("请求PAAS服务异常", e);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
    }


    /**
     * 获取历史消息
     *
     * @param
     * @return
     */
    public JSONObject getMessageLists(Map<String, Object> param) {
        String url = api + "/api/v2/message/lists";
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 获取历史消息
     *
     * @param param 请求参数
     * @return 响应对象
     */
    public PaasMessageListRspDTO getMessageList2(Map<String, Object> param) {
        String url = api + "/api/v2/message/lists";
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));

        String rspStr = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rspStr);
        JSONObject respData = result.getJSONObject(HttpConstant.DATA);
        return JsonUtil.objectFromJSONString(respData.toString(), PaasMessageListRspDTO.class);
    }

    /**
     * 设置审核开关接口
     *
     * @param
     * @return
     */
    public JSONObject setChannelSwitch(Map<String, Object> param) {
        String url = api + "/api/v2/channel/set-channel-switch";
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        log.info("PAAS接口:set-channel-switch返回结果:{}", result);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 获取审核开关状态接口
     *
     * @param
     * @return
     */
    public JSONObject getChannelSwitch(Map<String, Object> param) {
        String url = api + "/api/v2/channel/get-channel-switch";
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 获取待审核消息列表
     *
     * @param
     * @return
     */
    public JSONObject auditLists(Map<String, Object> param) {
        String url = api + "/api/v2/message/get-chat-audit-lists";
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        String s = result.toJSONString();
        Map map = JSON.parseObject(s, HashMap.class);
        String data = JSON.toJSONString(map.get(HttpConstant.DATA));
        if ("[]".equals(data) || "{}".equals(data)) {
            return null;
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 获取审核开关状态接口
     *
     * @param
     * @return
     */
    public JSONObject setChannelSwitchOptions(Map<String, Object> param) {
        String url = api + "/api/v2/channel/set-channel-switch-options";
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        log.info("PAAS接口:set-channel-switch-options返回结果:{}", result);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 检查用户是否在线
     *
     * @param channelId
     * @param accountIdList
     */
    public Map<String, Object> checkUserOnlineByChannel(String channelId, List<Integer> accountIdList) {

        String url = api + "/api/v2/channel/check-user-online";
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("third_party_user_ids", Joiner.on(",").join(accountIdList));
        params.put(PaasCommonConstant.CHANNEL_ID_KEY, channelId);
        params.put(PaasCommonConstant.APP_ID_KEY, appId);
        params.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        params.put(PaasCommonConstant.SIGN, sign(params));
        String rspStr = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rspStr);

        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(params), rspStr);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        JSONObject data = result.getJSONObject(HttpConstant.DATA);
        Map<String, Object> resultMap = data.getJSONObject("connections");
        for (Map.Entry<String, Object> entry : resultMap.entrySet()) {
            int val = ((Integer) entry.getValue() >= 1) ? 1 : 0;
            resultMap.replace(entry.getKey(), val);
        }
        return resultMap;

    }

    /**
     * 获取频道下所有在线用户ID
     *
     * @param channelId 频道ID
     * @return id list
     */
    public List<Integer> listAllOnlineUserId(String channelId) {
        int page = 1;
        int size = 1000;
        List<Integer> result = new ArrayList<>();
        while (true) {
            List<Integer> ids = getUserIdList(channelId, page, size);
            if (CollectionUtils.isEmpty(ids)) {
                break;
            }
            result.addAll(ids);
            page++;
        }
        return result;

    }

    /**
     * 获取聊天频道在线用户列表
     *
     * @param channelId 频道id
     * @param page      页码
     * @param pageSize  每页大小
     */
    public List<Integer> getUserIdList(String channelId, Integer page, Integer pageSize) {
        String url = api + "/api/v2/channel/get-userid-list";
        HashMap<String, Object> params = Maps.newHashMap();
        params.put(PaasCommonConstant.CURR_PAGE_KEY, page);
        params.put(PaasCommonConstant.PAGE_SIZE_KEY, pageSize);
        params.put(PaasCommonConstant.CHANNEL_ID_KEY, channelId);
        params.put(PaasCommonConstant.APP_ID_KEY, appId);
        params.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        // 构建sign
        params.put(PaasCommonConstant.SIGN, sign(params));
        String rspStr = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rspStr);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(params), rspStr);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        JSONObject data = result.getJSONObject(HttpConstant.DATA);
        List<Integer> ids = new ArrayList<>();
        if (null != data) {
            JSONArray arr = data.getJSONArray("third_party_user_id");
            arr.stream().mapToInt(r -> Integer.parseInt(r.toString())).forEach(ids::add);
        }
        return ids;
    }

    /**
     * 获取在线人数
     *
     * @param channelId 频道ID
     * @return 在线人数
     * @link http://www.vhallyun.com/docs/show/1336
     */
    public Long getUserOnlineCount(String channelId) {
        String url = api + "/api/v2/channel/user-online-count";
        HashMap<String, Object> params = Maps.newHashMap();
        params.put(PaasCommonConstant.CHANNEL_ID_KEY, channelId);
        params.put(PaasCommonConstant.APP_ID_KEY, appId);
        params.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        // 构建sign
        params.put(PaasCommonConstant.SIGN, sign(params));
        String rspStr = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rspStr);
        if (result.getInteger(HttpConstant.CODE) == 200) {
            String count = result.getJSONObject(HttpConstant.DATA).getString("count");
            return StringUtils.isBlank(count) ? 0L : Long.parseLong(count);
        }

        return 0L;
    }

    /**
     * 获取在线连接数
     *
     * @param channelId 频道ID
     * @return 在线连接数
     * @link http://www.vhallyun.com/docs/show/1338
     */
    public Integer getConnectionCount(String channelId) {
        String url = api + "/api/v2/channel/connection-count";
        Map<String, Object> params = Maps.newHashMap();
        params.put(PaasCommonConstant.CHANNEL_ID_KEY, channelId);
        params.put(PaasCommonConstant.APP_ID_KEY, appId);
        params.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        // 构建sign
        params.put(PaasCommonConstant.SIGN, sign(params));

        String rspStr = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rspStr);
        Integer code = result.getInteger(HttpConstant.CODE);
        if (code != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(params), rspStr);
            //401为应用的token失效报错 会导致自动登出
            if (code == HttpConstant.UNAUTH_CODE) {
                throw new BusinessException(409, result.getString(HttpConstant.MSG), "error.paas.connection");
            }
            throw new BusinessException(result.getInteger(HttpConstant.CODE), result.getString(HttpConstant.MSG), "error.paas.connection");
        }
        return result.getJSONObject(HttpConstant.DATA).getInteger("count");
    }

    /**
     * 获取流状态
     *
     * @param roomIds
     * @return
     */
    public JSONObject getStreamStatus(String roomIds) {
        Map<String, Object> map = new HashMap<>(16);
        map.put("room_ids", roomIds);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String url = api + "/api/v2/room/get-stream-status";
        String rsp = httpPostAndPrintLog(url, map);
        return JSON.parseObject(rsp);
    }

    /**
     * 获取消息总数
     *
     * @param roomId
     * @return
     */
    public JSONObject getMessageCount(String roomId) {
        Map<String, Object> map = new HashMap<>(16);
        map.put(PaasCommonConstant.CHANNEL_ID_KEY, roomId);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String url = api + "/api/v2/channel/send-message-stat";
        String rsp = httpPostAndPrintLog(url, map);
        return JSON.parseObject(rsp);
    }

    /**
     * 获取消息总数
     *
     * @param channelId PAAS频道ID
     * @param startTime 开始时间
     * @return total
     */
    public Integer getMessageCount(String channelId, String startTime, String endTime) {
        Map<String, Object> map = new HashMap<>(16);
        map.put(PaasCommonConstant.CHANNEL_ID_KEY, channelId);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.START_TIME_KEY, startTime);
        map.put(PaasCommonConstant.END_TIME_KEY, endTime);
        map.put(PaasCommonConstant.MSG_TYPE_KEY, "text,image");
        map.put(PaasCommonConstant.SIGN, sign(map));
        String url = api + "/api/v2/message/lists";
        String rsp = httpPostAndPrintLog(url, map);
        JSONObject jsonObject = JSONObject.parseObject(rsp);
        JSONObject data = jsonObject.getJSONObject(HttpConstant.DATA);
        if (data == null) {
            return 0;
        }
        return data.getInteger(PaasCommonConstant.TOTAL);
    }

    /**
     * 创建accessToken
     *
     * @param map
     * @return
     */
    public JSONObject createAccessToken(Map<String, Object> map) {
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String url = api + "/api/v1/base/create-access-token";
		/*String rsp = httpPostAndLog(map, url);
		JSONObject result = JSON.parseObject(rsp);*/
        String rspStr = httpPostAndPrintLog(url, map);
        return JSON.parseObject(rspStr);
    }

    /**
     * 获取房间的回放列表
     */
    public JSONObject getRecordList(Map<String, Object> param) {
        String url = api + "/api/v2/vod";
        param.put(PaasCommonConstant.ACTION_KEY, "GetVodList");
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 删除回放信息
     */
    public JSONObject recordDel(Map<String, Object> param) {
        String url = api + "/api/v2/vod";
        param.put(PaasCommonConstant.ACTION_KEY, "SubmitDeleteVodTasks");
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 更改回放名称
     */
    public void changeName(Map<String, Object> param) {
        String url = api + "/api/v2/vod";
        param.put(PaasCommonConstant.ACTION_KEY, "UpdateVodInfo");
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
    }

    /**
     * 删除某个清晰度
     */
    public JSONObject videoDel(Map<String, Object> param) {
        String url = api + "/api/v2/vod";
        param.put(PaasCommonConstant.ACTION_KEY, "SubmitDeleteVideoTasks");
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 获取音视频详情
     */
    public JSONObject recordInfo(Map<String, Object> param) {
        String url = api + "/api/v2/vod";
        param.put(PaasCommonConstant.ACTION_KEY, "GetVodInfo");
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 获取视频详情
     *
     * @param vodId
     * @return
     */
    public JSONObject getRecordInfo(String vodId) {
        String url = api + "/api/v2/vod";
        Map<String, Object> map = new HashMap<>(16);
        map.put(PaasCommonConstant.VOD_ID_KEY, vodId);
        map.put("acquire_video_info", 1);
        map.put(PaasCommonConstant.ACTION_KEY, "GetVodInfo");
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String rsp = httpPostAndPrintLog(url, map);
        JSONObject result = JSON.parseObject(rsp);
        return result;
    }

    /**
     * 获取回放信息
     *
     * @param params
     * @return
     */
    public JSONObject getVodInfo(Map<String, Object> params) {
        String url = api + "/api/v2/vod";
        params.put("acquire_video_info", 1);
        params.put(PaasCommonConstant.ACTION_KEY, "GetVodInfo");
        params.put(PaasCommonConstant.APP_ID_KEY, appId);
        params.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        params.put(PaasCommonConstant.SIGN, sign(params));
        String rsp = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(params), rsp);
        }

        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            //401为应用的token失效报错 会导致自动登出
            if (result.getInteger(HttpConstant.CODE) == HttpConstant.UNAUTH_CODE) {
                throw new BusinessException(409, result.getString(HttpConstant.MSG), "error.paas.vodinfo");
            }
            throw new BusinessException(result.getInteger(HttpConstant.CODE), result.getString(HttpConstant.MSG), "error.paas.vodinfo");
        }
        return result;
    }

    /**
     * 流媒体拉流
     *
     * @param
     * @return
     */
    public Boolean pullStream(String targetId, String sourceId, Integer sessionId, String command) {
        command = command == null ? "start" : command;
        String url = pullStreamUrl + "/api/relaystream";
        Map<String, Object> map = new HashMap<>(16);
        map.put("sessionid", sessionId.toString());
        map.put("command", command);
        map.put("source_streamid", sourceId);
        map.put("target_streamid", targetId);
        map.put("bu", "1");

        Long start = DateUtil.currentSeconds();

        String rsp = httpPostAndPrintLog(url, map);
        Long end = DateUtil.currentSeconds();
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) == 100) {
            return true;
        } else {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(map), rsp);
            return false;
        }
    }

    /**
     * 获取当前文档信息
     *
     * @param
     * @return
     */
    public JSONObject getDocumentWatchInfo(String channelId) {
        String url = api + "/api/v2/document/get-watch-info";
        Map<String, Object> map = new HashMap<>(16);
        map.put(PaasCommonConstant.CHANNEL_ID_KEY, channelId);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String rsp = httpPostAndPrintLog(url, map);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(map), rsp);
            throw new BusinessException(result.getInteger(HttpConstant.CODE), result.getString(HttpConstant.MSG), "error.paas.doc");
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 文档消息转发
     *
     * @param
     * @return
     */
    public Boolean setTargetChannel(String channelId, String targetChannel) {
        String url = api + "/api/v2/channel/set-target-channel";
        Map<String, Object> map = new HashMap<>(16);
        map.put(PaasCommonConstant.CHANNEL_ID_KEY, channelId);
        map.put("target_channel", targetChannel);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String rsp = httpPostAndPrintLog(url, map);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(map), rsp);
            throw new BusinessException(result.getInteger(HttpConstant.CODE), result.getString(HttpConstant.MSG), "error.paas.channel");
        } else {
            return true;
        }

    }

    /**
     * 文档消息转发
     *
     * @param
     * @return
     */
    public Boolean resetTargetChannel(String channelId) {
        String url = api + "/api/v2/channel/reset-target-channel";
        Map<String, Object> map = new HashMap<>(16);
        map.put(PaasCommonConstant.CHANNEL_ID_KEY, channelId);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String rsp = httpPostAndPrintLog(url, map);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(map), rsp);
            throw new BusinessException(result.getInteger(HttpConstant.CODE), result.getString(HttpConstant.MSG), "error.paas.channel");
        } else {
            return true;
        }
    }

    public JSONObject createRecord(String streamId, String startTime, String endTime) {
        String url = api + "/api/v2/vod";
        Map<String, Object> map = new HashMap<>(16);
        map.put("stream_id", streamId);
        map.put(PaasCommonConstant.START_TIME_KEY, startTime);
        map.put(PaasCommonConstant.END_TIME_KEY, endTime);
        map.put(PaasCommonConstant.ACTION_KEY, "SubmitCreateRecordTasks");
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String rsp = httpPostAndPrintLog(url, map);
        return JSON.parseObject(rsp);
    }

    public Boolean applyMessageSend(Map<String, Object> param) {
        String url = api + "/api/v2/message/apply-message-send";
        int timeout = 3000;
        String msgId = (String) param.get(PaasCommonConstant.MSG_ID_KEY);
        int length = msgId.length();
        if (length > 1000) {
            timeout = 20000;
        }
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(result.getInteger(HttpConstant.CODE), result.getString(HttpConstant.MSG), "error.paas.msg");
        }
        return true;
    }

    public JSONObject getFormInfo(String questionId) {
        String url = api + "/api/v2/form/get";
        Long time = DateUtil.currentSeconds();
        Map<String, Object> param = new HashMap<>(16);
        param.put("id", questionId);
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put("bu", bu);
        param.put(PaasCommonConstant.SIGNED_AT, time);
        HttpResponse rsp = HttpUtil.createPost(url).contentType("multipart/form-data").form("id", questionId).form(PaasCommonConstant.APP_ID_KEY, appId)
                .form("bu", bu).form(PaasCommonConstant.SIGNED_AT, time).form(PaasCommonConstant.SIGN, sign(param)).execute();
        JSONObject result = JSON.parseObject(rsp.body());

        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,失败,path=[{}], rsp=[{}]", url, rsp.body());
            String msg = result.getString(HttpConstant.MSG);
            Integer code = result.getInteger(HttpConstant.CODE);
            throw new BusinessException(code, msg, "error.paas.form");
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    public JSONObject createForm(Map<String, Object> param) {
        String url = api + "/api/v2/form/create";
        param.remove(PaasCommonConstant.SIGN);
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put("bu", bu);
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.SIGN, sign(param));

        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,失败,path=[{}], param=[{}], rsp=[{}]", url, JSON.toJSONString(param), rsp);
            String msg = result.getString(HttpConstant.MSG);
            Integer code = result.getInteger(HttpConstant.CODE);
            throw new BusinessException(code, msg, "error.paas.form");
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    public JSONObject answerCreate(Map<String, Object> param) {
        String url = api + "/api/v2/answer/create";
        param.remove(PaasCommonConstant.SIGN);
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.SIGN, sign(param));

        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("回答表单的操作接口,失败,path=[{}], param=[{}], rsp=[{}]", url, JSON.toJSONString(param), rsp);
            String msg = result.getString(HttpConstant.MSG);
            Integer code = result.getInteger(HttpConstant.CODE);
            throw new BusinessException(code, msg, "error.paas.form");
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    public JSONObject delRoom(String roomId) {
        Map<String, Object> map = new HashMap<>(16);
        map.put(PaasCommonConstant.ROOM_ID, roomId);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String url = api + "/api/v2/room/delete";
        String rsp = httpPostAndPrintLog(url, map);
        return JSON.parseObject(rsp);
    }

    public JSONObject delInav(String inavId) {
        Map<String, Object> map = new HashMap<>(16);
        map.put(PaasCommonConstant.INAV_ID, inavId);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String url = api + "/api/v2/inav/delete";
        String rsp = httpPostAndPrintLog(url, map);
        return JSON.parseObject(rsp);
    }

    public JSONObject delChannel(String channelId) {
        Map<String, Object> map = new HashMap<>(16);
        map.put(PaasCommonConstant.CHANNEL_ID_KEY, channelId);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String url = api + "/api/v2/channel/delete";
        String rsp = httpPostAndPrintLog(url, map);
        return JSON.parseObject(rsp);
    }

    public JSONObject getPushInfo(String roomId, String expireTime) {
        Map<String, Object> map = new HashMap<>(16);
        map.put(PaasCommonConstant.ROOM_ID, roomId);
        map.put("expire_time", expireTime);
        map.put(PaasCommonConstant.APP_ID_KEY, appId);
        map.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        map.put(PaasCommonConstant.SIGN, sign(map));
        String url = api + "/api/v2/room/get-push-info";
        String rsp = httpPostAndPrintLog(url, map);
        return JSON.parseObject(rsp);
    }

    public JSONObject getAnswerDetail(Integer questionId, Integer answerId) {
        String url = api + "/api/v2/answer/get";
        Long time = DateUtil.currentSeconds();
        Map<String, Object> param = new HashMap<>(16);
        param.put("id", questionId);
        param.put("answer_id", answerId);
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put("bu", bu);
        param.put(PaasCommonConstant.SIGNED_AT, time);
        HttpResponse rsp = HttpUtil.createPost(url).contentType("multipart/form-data").form("id", questionId)
                .form("answer_id", answerId).form(PaasCommonConstant.APP_ID_KEY, appId).form("bu", bu).form(PaasCommonConstant.SIGNED_AT, time)
                .form(PaasCommonConstant.SIGN, sign(param)).execute();
        JSONObject result = JSON.parseObject(rsp.body());

        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.warn("三方接口,失败,path=[{}], rsp=[{}]", url, rsp.body());
            String msg = result.getString(HttpConstant.MSG);
            Integer code = result.getInteger(HttpConstant.CODE);
            throw new BusinessException(code, msg, "error.paas.answer");
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    public String buildPassUrl(RoomsEntityDTO room, long accountId) {
        long signAt = DateUtil.currentSeconds();
        Map<String, Object> param = buildPassParam(signAt, room, accountId);
        String sign = sign(param);
        String url = api + "/api/v1/base/create-access-token" + "?third_party_user_id=" + accountId + "" + "&publish_stream=" + room
                .getRoomId() + "" + "&chat=" + room.getChannelId() + "" + "&operate_document=" + room.getChannelId() + ""
                + "&kick_inav=" + room.getInavId() + "" + "&publish_inav_stream=" + room.getInavId() + "" + "&kick_inav_stream="
                + room.getInavId() + "" + "&askfor_inav_publish=" + room.getInavId() + "" + "&audit_inav_publish=" + room
                .getInavId() + "" + "&publish_inav_another=" + room.getInavId() + "" + "&apply_inav_publish=" + room.getInavId()
                + "" + "&data_collect_manage=all" + "&data_collect_submit=all" + "&data_collect_view=all" + "&app_id=" + appId + ""
                + "&signed_at=" + signAt + "" + "&sign=" + sign;
        return url;
    }


    /**
     * 创建推流配置
     *
     * @param param
     * @return
     */
    public JSONObject startpushStreamConfig(Map<String, Object> param) {
        String url = api + "/api/v2/room/create-live-push-stream-config";
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            String msg = result.getString(HttpConstant.MSG);
            Integer code = result.getInteger(HttpConstant.CODE);
            throw new BusinessException(code, msg, "error.paas.stream");
        }
        return result.getJSONObject(HttpConstant.DATA);

    }

    /**
     * 删除推流配置
     *
     * @param param
     * @return
     */
    public Boolean deleteStreamConfig(Map<String, Object> param) {
        String url = api + "/api/v2/room/delete-live-push-stream-config";
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            String msg = result.getString(HttpConstant.MSG);
            Integer code = result.getInteger(HttpConstant.CODE);
            throw new BusinessException(code, msg, "error.paas.stream");
        }
        return true;

    }

    /**
     * 构造pass签名需要的参数
     *
     * @param room      room
     * @param accountId account id
     * @return map
     */
    private Map<String, Object> buildPassParam(long signAt, RoomsEntityDTO room, long accountId) {
        TreeMap<String, Object> param = new TreeMap<>();
        param.put(PaasCommonConstant.THIRD_PARTY_USER_ID_KEY, accountId);
        param.put("publish_stream", room.getRoomId());
        param.put("chat", room.getChannelId());
        param.put("operate_document", room.getChannelId());
        param.put("kick_inav", room.getInavId());
        param.put("publish_inav_stream", room.getInavId());
        param.put("kick_inav_stream", room.getInavId());
        param.put("askfor_inav_publish", room.getInavId());
        param.put("audit_inav_publish", room.getInavId());
        param.put("publish_inav_another", room.getInavId());
        param.put("apply_inav_publish", room.getInavId());
        param.put("data_collect_manage", "all");
        param.put("data_collect_submit", "all");
        param.put("data_collect_view", "all");
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGNED_AT, signAt);
        return param;
    }

    /**
     * 提交点播转直播任务
     */
    public JSONObject submitVODToLive(Map<String, Object> param) {
        String url = api + "/api/v2/vod";
        param.put(PaasCommonConstant.ACTION_KEY, "SubmitVODToLive");
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));

//        //必填
//        param.put(PaasCommonConstant.VOD_ID_KEY,"点播ID");
//        param.put("cmd","start 开始转播stop 停止转播");
//        param.put(PaasCommonConstant.ROOM_ID,"直播房间ID");
//        //可选
//        param.put("quality","same \t直播房间ID\n" +
//                "quality\t否\tsame\t指定转播清晰度，取值范围：360p480p720p1080psame默认采用片源最高清晰度注意：指源点播清晰度，不是输出清晰度。选择清晰度不存在时，默认推流原画。");
//        param.put("loop","转播循环模式0 循环播放1 播放一次默认值1");
//        param.put("task_id","转播任务ID");
//        param.put(PaasCommonConstant.CHANNEL_ID_KEY,"纯视频直播可以不填，视频+文档直播必填，默认为纯视频直播");
//        param.put("options","video(纯视频)，video,document(视频+文档)");

        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        if (isJsonArray(result.get(HttpConstant.DATA))) {
            return new JSONObject();
        } else {
            return result.getJSONObject(HttpConstant.DATA);
        }
    }

    /**
     * 创建水平模版   在配置直播间水印的时候 需要该接口返回的模版ID
     * <p>
     * 配置直播水印需要创建水印模版，模版中配置了水印的位置，然后在给房间配置水印模版ID 直播间就有水印了
     * 该水印模版兼容播放器和转码 但这两方方式需要单独配置
     * 配置了播放器水印，只在直播时有水印，而在转码的视频或者回放中没有
     * 需要单独配置转码水印才可以
     *
     * @param param 参数
     * @return JSONObject
     */
    public JSONObject createWatermarkTemp(Map<String, Object> param) {
        String url = api + "/api/v2/watermark/create";
        File file = (File) param.get("watermark_image");
        param.remove("watermark_image");
        param.put("signed_at", DateUtil.currentSeconds());
        param.put("app_id", appId);
        param.put("sign", sign(param));
        HttpResponse rsp = HttpUtil.createPost(url).contentType("multipart/form-data")
                .form("app_id", appId)
                .form("signed_at", param.get("signed_at"))
                .form("watermark_image", file)
                .form("watermark_name", param.get("watermark_name"))
                .form("watermark_positiontype", param.get("watermark_positiontype"))
                .form("sign", param.get("sign"))
                .execute();
        JSONObject result = JSON.parseObject(rsp.body());
        if (result.getInteger("code") != 200) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            if (result.getInteger("code").equals(40034)) {
                throw new BusinessException(BizErrorCode.BIZ_PAAS_CREATE_WATERMARK_40034_FAILED);
            } else if (result.getInteger("code").equals(70003)) {
                throw new BusinessException(BizErrorCode.BIZ_PAAS_CREATE_WATERMARK_70003_FAILED);
            } else {
                throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
            }

        }
        if (isJsonArray(result.get("data"))) {
            return new JSONObject();
        } else {
            return result.getJSONObject("data");
        }
    }

    /**
     * 更新水印模板
     *
     * @param param 参数
     * @return JSONObject
     */
    public JSONObject updateWatermarkTemp(Map<String, Object> param) {
        File file = (File) param.get("watermark_image");
        param.remove("watermark_image");
        String url = api + "/api/v2/watermark/update";
        param.put("signed_at", DateUtil.currentSeconds());
        param.put("app_id", appId);
        param.put("bu", bu);
        param.put("sign", sign(param));

        HttpRequest httpRequest = HttpUtil.createPost(url).contentType("multipart/form-data")
                .form("app_id", appId)
                .form("signed_at", param.get("signed_at"))
                .form("bu", bu)
                .form("watermark_positiontype", param.get("watermark_positiontype"))
                .form("watermark_name", param.get("watermark_name"))
                .form("watermark_id", param.get("watermark_id"))
                .form("sign", param.get("sign"));

        if (Objects.nonNull(file)) {
            httpRequest.form("watermark_image", file);
        }
        JSONObject result = JSON.parseObject(httpRequest.execute().body());
        if (result.getInteger("code") != 200) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), httpRequest);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        if (isJsonArray(result.get("data"))) {
            return new JSONObject();
        } else {
            return result.getJSONObject("data");
        }
    }

    /**
     * 设置转码水印
     *
     * @param param
     * @return
     */
    public JSONObject setStreamWatermark(Map<String, Object> param) {
        String url = api + "/api/v2/room/set-room-stream-watermark";
        return commonPostPaaSUrl(param, url);
    }

    /**
     * 查看水印模板列表
     * https://www.vhallyun.com/docs/show/108
     *
     * @param param 参数
     *              参数名称	参数类型	是否必须	示例	备注
     *              pos	text	否	10	获取条目节点，默认为 0。eg : 10 从第10条开始查询
     *              limit	text	否	10	获取条目数量，默认为10条，最大为1000条
     * @return 请求返回结果
     */
    public JSONArray getWatermarkList(Map<String, Object> param) {
        String url = api + "/api/v2/watermark/lists";
        param.put("signed_at", DateUtil.currentSeconds());
        param.put("app_id", appId);
        param.put("sign", sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        Integer code = result.getInteger("code");
        if (code != 200) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
//            "code":20015,"msg":"水印模板查询为空"
            if (code == 20015) {
                return new JSONArray();
            }
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONArray("data");
    }

    /**
     * 删除水印模板
     * https://www.vhallyun.com/docs/show/106
     *
     * @param param 参数
     *              参数名称	参数类型	是否必须	示例	备注
     *              watermark_id	text	是	1	模板ID
     * @return JSONObject
     */
    public JSONObject deleteWatermark(Map<String, Object> param) {
        String url = api + "/api/v2/watermark/delete";
        return commonPostPaaSUrl(param, url);
    }

    /**
     * 配置直播水印-设置默认水印
     * https://www.vhallyun.com/docs/show/103
     *
     * @param param 参数
     *              <p>
     *              参数名称	参数类型	是否必须	示例	备注
     *              watermark_id	text	否	9	水印模板id,为0或空时不展示水印
     * @return JSONObject
     */
    public JSONObject defaultWatermark(Map<String, Object> param) {
        String url = api + "/api/v2/room/set-watermark";
        return commonPostPaaSUrl(param, url);
    }


    private JSONObject commonPostPaaSUrl(Map<String, Object> param, String url) {
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));

        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        int code = result.getInteger("code");
        if (code != 200) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            if (code == 40032) {
                throw new BusinessException(code, result.getString("msg"), "");
            }
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        if (isJsonArray(result.get("data"))) {
            return new JSONObject();
        } else {
            return result.getJSONObject("data");
        }
    }

    /**
     * 获取水印信息
     *
     * @param watermarkId
     * @return
     */
    public JSONObject getWatermarkInfo(Integer watermarkId) {
        Map<String, Object> param = new HashMap<>();
        param.put("watermark_id", watermarkId.toString());
        String url = api + "/api/v2/watermark/view";
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger("code") != 200) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }

        return result.getJSONObject("data");

    }


    /**
     * 开播记录上报
     *
     * @param recordReport 上报数据
     * @return true=上报成功 false=上报失败
     */
    public boolean broadcastRecordReport(BigDataBroadcastRecordReportDTO recordReport) {
        String url = String.format("%s/api/v2/data/live-inav-chat-room", prefixUrl);
        try {
            Map params = JsonUtil.objectFromJSONString(JsonUtil.toJsonString(recordReport), Map.class);
            String rspStr = httpPostAndPrintLog(url, params);
            JSONObject result = JSON.parseObject(rspStr);
            String msg = result.getString(HttpConstant.MSG);
            Integer code = result.getInteger(HttpConstant.CODE);
            if (code != HttpConstant.SUCCESS_CODE) {
                log.error("数据上报失败，request={}, response={}", params, result);
                throw new BusinessException(code, msg, "failed");
            }
            return true;

        } catch (Exception e) {
            log.error("数据上报请求异常", e);
            if (e instanceof BusinessException) {
                throw new BusinessException(50000, "数据上报异常", "failed");
            }
            return false;
        }
    }

    public Boolean sendPayStatusParams(Map<String, Object> params, String url) {
        HashMap<String, Object> statusParams = new HashMap<>(8);
        statusParams.put("app_id", params.get("app_id"));
        statusParams.put("trade_no", params.get("biz_order_no"));
        statusParams.put("pay_status", Objects.equals("SUCCESS", params.get("pay_status")) ? 1 : 2);
        statusParams.put("third_party_trade_no", params.get("trade_no"));
        statusParams.put("channel", params.get("channel"));
        String rspStr = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rspStr);
        JSONObject data = result.getJSONObject(HttpConstant.DATA);
        Integer code = result.getInteger(HttpConstant.CODE);
        if (code != HttpConstant.SUCCESS_CODE || data == null) {
            log.error("请求接口失败,path={},rsp={}", url, rspStr);
            return false;
        }
        return true;
    }

    public JSONObject saveRecord(CutRecordReqVO reqVO) {

        Map<String, Object> paramMap = new HashMap<>(8);
        paramMap.put("cut_sections", reqVO.getCutSections());
        paramMap.put("point_sections", reqVO.getPointSections());
        paramMap.put("ts_cut_type", reqVO.getCutType());
        paramMap.put(PaasCommonConstant.VOD_ID_KEY, reqVO.getVodId());
        paramMap.put(PaasCommonConstant.ACTION_KEY, "SubmitVideoEditTasks");
        paramMap.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        paramMap.put(PaasCommonConstant.APP_ID_KEY, appId);
        paramMap.put("sign", "vhall");
        //需要加个公用的host,// 生成回放
        String url = api + "/api/v2/vod";
        String rspStr = httpPostAndPrintLog(url, paramMap);
        JSONObject result = JSON.parseObject(rspStr);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("裁剪保存失败:{}", rspStr);
            throw new BusinessException(BizErrorCode.EMPTY_VIDEO);
        }
        return result;
    }

    /**
     * https://www.vhallyun.com/docs/show/221
     * 点播添加打点信息
     * @param reqVO
     * @return
     */
    public JSONObject addKeyFrameDesc(AddKeyFrameDescReqVO reqVO) {

        Map<String, Object> paramMap = new HashMap<>(8);
        paramMap.put("point_sections", reqVO.getPointSections());
        paramMap.put(PaasCommonConstant.VOD_ID_KEY, reqVO.getVodId());
        paramMap.put(PaasCommonConstant.ACTION_KEY, "AddKeyFrameDesc");
        paramMap.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        paramMap.put(PaasCommonConstant.APP_ID_KEY, appId);
        paramMap.put("sign", "vhall");
        //需要加个公用的host,// 生成回放
        String url = api + "/api/v2/vod";
        String rspStr = httpPostAndPrintLog(url, paramMap);
        JSONObject result = JSON.parseObject(rspStr);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("打点保存失败:{}", rspStr);
            throw new BusinessException(BizErrorCode.EMPTY_VIDEO);
        }
        return result;
    }

    public JSONObject downRecord(RecordDownReqVO reqVO) {
        String url = api + "/api/v2/vod";
        Map<String, Object> params = new HashMap<>(8);
        params.put(PaasCommonConstant.VOD_ID_KEY, reqVO.getRecordId());
        params.put(PaasCommonConstant.ACTION_KEY, "SubmitMediaPackageTasks");

        params.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        params.put(PaasCommonConstant.APP_ID_KEY, appId);
        if (StringUtils.isNotBlank(reqVO.getVideoId())) {
            params.put(PaasCommonConstant.VIDEO_ID_KEY, reqVO.getVideoId());
        }
        params.put("sign", "vhall");
        String rspStr = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rspStr);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            if (result.getInteger(HttpConstant.CODE) == 5002){
                throw new BusinessException(60000,"下载任务处理中,请稍等","");
            }
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(params), rspStr);
            throw new BusinessException(BizErrorCode.EMPTY_VIDEO);
        }
        return result;
    }

    public JSONObject downRecordQuality(RecordDownQualityReqVO reqVO) {
        String url = api + "/api/v2/vod";
        Map<String, Object> params = new HashMap<>(8);
        params.put(PaasCommonConstant.VOD_ID_KEY, reqVO.getRecordId());
        params.put("quality", reqVO.getQuality());
        params.put(PaasCommonConstant.ACTION_KEY, "SubmitMediaPackageByQualityTasks");
        params.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        params.put(PaasCommonConstant.APP_ID_KEY, appId);
        if (StringUtils.isNotBlank(reqVO.getVideoId())) {
            params.put(PaasCommonConstant.VIDEO_ID_KEY, reqVO.getVideoId());
        }
        params.put("sign", "vhall");
        String rspStr = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rspStr);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(params), rspStr);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result;
    }

    /**
     * 设置频道限流
     *
     * @param params      参数
     * @param channelRoom 频道信息
     * @return
     */
    public Boolean setChannelLimit(HashMap<String, Object> params, String channelRoom) {
        String url = api + "/api/v2/channel/set-channel-limit";
        params.put("type", 1);
        params.put("limit", 30);
        params.put("ttl", 1);
        params.put("frequency_limit", 1);
        params.put("channel_id", channelRoom);
        params.put("service_type", "service_im");
        params.put("sign", sign(params));

        String rspStr = httpPostAndPrintLog(url, params);

        JSONObject result = JSON.parseObject(rspStr);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(params), rspStr);
            return false;
        }
        return result.getInteger(HttpConstant.CODE) == 200;
    }

    /**
     * /api/v2/room/create  请求 获取 room_id
     *
     * @param params
     * @return
     */
    public String createLiveRoom(HashMap<String, Object> params, String url, int type) {
        url = api + url;
        String rspStr = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rspStr);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(params), rspStr);
            return "";
        } else {
            JSONObject data = result.getJSONObject(HttpConstant.DATA);
            if (type == RoomConstant.INT_FACE1) {
                return data.getString("room_id");
            }
            if (type == RoomConstant.INT_FACE2) {
                return data.getString("inav_id");
            }
            if (type == RoomConstant.INT_FACE3) {
                return data.getString("channel_id");
            }
        }
        return "";
    }

    /**
     * 设置发送表情限频
     *
     * @param params      参数
     * @param channelRoom 频道信息
     * @param url         API地址
     */
    public Boolean setGiftLimit(HashMap<String, Object> params, String channelRoom, String url) {
        url = api + url;
        params.put("type", 1);
        params.put("limit", 18);
        params.put("ttl", 1);
        params.put("frequency_limit", 2);
        params.put("channel_id", channelRoom);
        params.put("service_type", "service_room");
        params.put("event_type", SendMessageTypeEnum.GIFT_SEND_SUCCESS.getType());
        params.put("sign", sign(params));
        String rspStr = httpPostAndPrintLog(url, params);
        JSONObject result = JSON.parseObject(rspStr);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(params), rspStr);
            return false;
        }
        return result.getInteger(HttpConstant.CODE) == 200;
    }


    /**
     * 获取房间的回放列表
     */
    public JSONObject getVodSnapshotInfo(FirstFrameFromVideoVO reqVO) {
        String url = api + "/api/v2/vod";
        Map<String, Object> param = new HashMap<>(8);
        param.put(PaasCommonConstant.ACTION_KEY, "GetVodSnapshotInfo");
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put("vod_id", reqVO.getDemandVodId());
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 提交生成媒体封面图任务
     */
    public JSONObject submitCoverTasks(FirstFrameFromVideoVO reqVO) {
        String url = api + "/api/v2/vod";
        Map<String, Object> param = new HashMap<>(8);
        param.put(PaasCommonConstant.ACTION_KEY, "SubmitCoverTasks");
        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put("vod_id", reqVO.getDemandVodId());
        param.put("cover_type", 0);
        param.put(PaasCommonConstant.SIGN, sign(param));
        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 提交拉流任务
     */
    public JSONObject submitStartPullStream(String roomId, String pullStreamUrl) {
        String url = api + "/api/v2/room/create-live-pull-stream-config";
        Map<String, Object> param = new HashMap<>(8);

        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.ROOM_ID, roomId);
        param.put(PaasCommonConstant.PULL_STREAM_SOURCE_TYPE, PaasCommonConstant.PULL_STREAM_SOURCE_TYPE_VALUE);
        param.put(PaasCommonConstant.PULL_STREAM_SOURCE_URL, pullStreamUrl);
        param.put(PaasCommonConstant.START_TIME_KEY, DateUtil.offsetMillisecond(DateUtil.date(), PaasCommonConstant.PULL_STREAM_START_OFFSET));
        param.put(PaasCommonConstant.END_TIME_KEY, DateUtil.offsetMillisecond(DateUtil.date(), PaasCommonConstant.PULL_STREAM_END_OFFSET));
        param.put(PaasCommonConstant.SIGN, sign(param));

        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);

        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
        return result.getJSONObject(HttpConstant.DATA);
    }

    /**
     * 结束拉流任务
     */
    public void submitDelPullStream(Integer configID) {
        String url = api + "/api/v2/room/delete-live-pull-stream-config";
        Map<String, Object> param = new HashMap<>(8);

        param.put(PaasCommonConstant.SIGNED_AT, DateUtil.currentSeconds());
        param.put(PaasCommonConstant.APP_ID_KEY, appId);
        param.put(PaasCommonConstant.PULL_STREAM_CONFIG_ID, configID);
        param.put(PaasCommonConstant.SIGN, sign(param));

        String rsp = httpPostAndPrintLog(url, param);
        JSONObject result = JSON.parseObject(rsp);

        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.error("三方接口,调用失败: url:{},param:{},result:{}", url, JSON.toJSONString(param), rsp);
            throw new BusinessException(BizErrorCode.BIZ_PAAS_FAILED);
        }
    }

}
